package com.czy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

/**
 * 单个任务比较耗时才用并行流 不然会更慢
 */
public class 并行流 {
    public static class User {
        public int id;
        public int money;

        public User(int id, int money) {
            this.id = id;
            this.money = money;
        }
    }
    // 并行 2278 2254 2337
    // 串行 1476 1081 1377 1372 1365 1333 1341 1331 1363 1404 4220 4143
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            users.add(new User(i, ThreadLocalRandom.current().nextInt(0, 5000000)));
        }
        long sum = users.stream().flatMapToLong(user -> LongStream.of(user.money)).sum();
        double avg = users.stream().flatMapToLong(user -> LongStream.of(user.money)).average().orElse(0);
        System.out.println(sum);
        System.out.println(avg);
        long l = System.currentTimeMillis();
        Map<String, List<User>> map = users
                .stream()
                .parallel()
                .collect(Collectors.groupingBy(
                        user -> {
                            try {
                                // 耗时任务
                                Thread.sleep(1);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                            return user.money >= avg ? "高" : "低";
                        },
//                        HashMap::new,
                        ConcurrentHashMap::new,
                        Collector.of(
//                                () -> new ArrayList<User>(),
                                () -> Collections.synchronizedList(new ArrayList<User>()),
                                List::add,
                                (list1, list2) -> {
                                    list1.addAll(list2);
                                    return list1;
                                },
                                list -> list, Collector.Characteristics.CONCURRENT
                        )));
        System.out.println(System.currentTimeMillis() - l);
        for (Map.Entry<String, List<User>> stringCopyOnWriteArrayListEntry : map.entrySet()) {
            System.out.println(stringCopyOnWriteArrayListEntry.getKey() + " " + stringCopyOnWriteArrayListEntry.getValue().size());
        }
    }
}
